﻿// ShellExt.cpp : Implementation of CShellExt

#include "stdafx.h"
#include "ShellExt.h"
#include <shobjidl.h>
#include "utils.h"
#include <Windows.h>
//IShellExtInit
HRESULT STDMETHODCALLTYPE CShellExt::Initialize(__in_opt PCIDLIST_ABSOLUTE pidlFolder, __in_opt IDataObject *pdtobj, __in_opt HKEY hkeyProgID)
{
	__DebugFunctionCall("Initialize");
	if(NULL == pdtobj)
	{
		__DebugLog("Right clicked on no shell objects.That mean user click desktop or explorer background.");
		return S_OK;
	}
	return S_OK;
}


HRESULT STDMETHODCALLTYPE CShellExt::QueryContextMenu(__in HMENU hmenu, __in UINT indexMenu, __in UINT idCmdFirst, __in UINT idCmdLast, __in UINT uFlags)
{
	__DebugFunctionCall("QueryContextMenu");

	HRESULT hr = E_INVALIDARG;
	if(CMF_DEFAULTONLY & uFlags)
	{
		return MAKE_HRESULT(SEVERITY_SUCCESS,FACILITY_NULL,USHORT(0));
	}

	__DebugLog("Inserting Menu Item.");
	UINT index = indexMenu;
	UINT id = idCmdFirst;
	UINT totalMenuNumber = GetAllMenusNumber();
	auto g_AllMenus = GetAllMenuInstatnce();

	//@TODO:Get Sub Menu Item Number.
	int itemCount = GetMenuItemCount(hmenu);
	wchar_t bzBuffer[1000];
	_itot_s(itemCount,bzBuffer,10);
	OutputDebugString(bzBuffer);
	//Find the New Menu
	for(int	 i =0;i<itemCount;i++)
	{
		GetMenuString(hmenu,i,bzBuffer,sizeof(bzBuffer)/sizeof(bzBuffer[0]),MF_BYPOSITION);
		OutputDebugString(bzBuffer);
		if(lstrcmpiW(bzBuffer,L"新建(&W)") == 0 || lstrcmpiW(bzBuffer,L"Ne&W") == 0)
		{
			auto subMenu = GetSubMenu(hmenu,i);
			auto mii = GenMenuItemInfo(g_AllMenus[2],id);
			if(!InsertMenuItem(subMenu,0,FALSE,&mii))
			{
				return HRESULT_FROM_WIN32(GetLastError());
			};
		}
	}
	InsertMenuItem(hmenu,0,TRUE,&GenMenuItemInfo(g_AllMenus[1],id));

	return MAKE_HRESULT(SEVERITY_SUCCESS,0,USHORT(totalMenuNumber));
}

HRESULT STDMETHODCALLTYPE CShellExt::InvokeCommand(__in CMINVOKECOMMANDINFO *pici)
{
	__DebugFunctionCall("CShellExt::InvokeCommand");
	auto g_AllMenus = GetAllMenuInstatnce();
	if(LOWORD(pici->lpVerb) < GetAllMenusNumber())
	{
		g_AllMenus[LOWORD(pici->lpVerb)].OnCommand(nullptr);
	}
	return S_OK;
}

HRESULT STDMETHODCALLTYPE CShellExt::GetCommandString(__in UINT_PTR idCmd, __in UINT uType, __reserved UINT *pReserved, __out_awcount(!(uType & GCS_UNICODE) , cchMax) LPSTR pszName, __in UINT cchMax)
{
	__DebugFunctionCall("CShellExt::GetCommandString");
	//TODO:not-necessary.
	return S_OK;
}

CShellExt::CShellExt()
{
	//__DebugFunctionCall("CShellExt::CShellExt() Constructor.");
}


HMENU CShellExt::GenPopupMenu(const CMenuInfo& info,UINT cmdId)
{
	__DebugFunctionCall("CShellExt::GenPopupMenu");
	HMENU popup = CreateMenu();
	UINT index = 0;
	for each(CMenuInfo *pInfo in info.subMenus)
	{
		auto mii = GenMenuItemInfo(*pInfo,cmdId);
		if(info.isPopup)
		{
			HMENU hSubMenu = GenPopupMenu(*pInfo,cmdId);
			mii.hSubMenu = hSubMenu;
		}
		InsertMenuItem(popup,index++,TRUE,&mii);
	}
	return popup;
}

MENUITEMINFO CShellExt::GenMenuItemInfo(const CMenuInfo &info,UINT cmdId)
{
	MENUITEMINFO mii = { sizeof(mii) };
	mii.wID = cmdId + info.menuID;
	mii.fType = MFT_STRING | MFT_RIGHTJUSTIFY;
	mii.dwTypeData = (LPWSTR)info.name;
	mii.fState = MFS_ENABLED;
	mii.fMask =  MIIM_STRING | MIIM_FTYPE |MIIM_ID | MIIM_STATE;
	if(NULL != info.hBitmapICon)
	{
		mii.fMask |= MIIM_CHECKMARKS;
		mii.hbmpChecked = static_cast<HBITMAP>(info.hBitmapICon);
		//mii.hbmpItem = static_cast<HBITMAP>(info.hBitmapICon);
		mii.hbmpUnchecked = static_cast<HBITMAP>(info.hBitmapICon);
	}
	if(info.isPopup)
	{
		mii.fMask |= MIIM_SUBMENU;
		mii.hSubMenu  = GenPopupMenu(info,cmdId);
	}
	return mii;
}





